package com.slz.crm.server.service.impl;

import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.slz.crm.common.excellistener.CustomerCompanyListener;
import com.slz.crm.common.exiception.BaseException;
import com.slz.crm.common.untils.AOTOExcelUntil;
import com.slz.crm.common.untils.BaseUnit;
import com.slz.crm.common.untils.ForeignKeyDeleteUtil;
import com.slz.crm.common.untils.ValidationUtils;
import com.slz.crm.pojo.dto.CustomerCompanyDTO;
import com.slz.crm.pojo.dto.CustomerMergeDTO;
import com.slz.crm.pojo.entity.CustomerCompanyEntity;
import com.slz.crm.pojo.entity.CustomerContactEntity;
import com.slz.crm.pojo.entity.CustomerMergeLogEntity;
import com.slz.crm.pojo.entity.UserEntity;
import com.slz.crm.pojo.excel.CustomerCompanyExcel;
import com.slz.crm.pojo.excel.GetCustomerCompanyExcel;
import com.slz.crm.pojo.vo.CustomerCompanyVO;
import com.slz.crm.pojo.vo.GroupResultVO;
import com.slz.crm.server.annotation.Privacy;
import com.slz.crm.server.constant.MessageConstant;
import com.slz.crm.server.mapper.CustomerCompanyMapper;
import com.slz.crm.server.mapper.CustomerContactMapper;
import com.slz.crm.server.mapper.CustomerMergeLogMapper;
import com.slz.crm.server.mapper.UserMapper;
import com.slz.crm.server.service.ContractOrderItemService;
import com.slz.crm.server.service.CustomerCompanyService;
import com.slz.crm.server.service.CustomerContactService;
import com.slz.crm.server.service.SalesOpportunityService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class CustomerCompanyServiceImpl extends ServiceImpl<CustomerCompanyMapper, CustomerCompanyEntity> implements CustomerCompanyService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private CustomerCompanyMapper customerCompanyMapper;

    @Autowired
    private CustomerMergeLogMapper customerMergeLogMapper;

    @Autowired
    private ForeignKeyDeleteUtil foreignKeyDeleteUtil;

    @Autowired
    private AOTOExcelUntil aotoExcelUntil;

    @Autowired
    private CustomerContactMapper customerContactMapper;

    @Autowired
    private CustomerContactService customerContactService;

    @Autowired
    private SalesOpportunityService salesOpportunityService;

    @Autowired
    private ContractOrderItemService contractOrderItemService;

    @Override
    public boolean add(CustomerCompanyDTO customerCompanyDTO) {

        isValid(customerCompanyDTO.getPhone());

        CustomerCompanyEntity customerCompanyEntity = new CustomerCompanyEntity();
        BeanUtils.copyProperties(customerCompanyDTO, customerCompanyEntity);

        Long currentId = BaseUnit.getCurrentId();

        customerCompanyEntity.setCreatorId(currentId);
        customerCompanyEntity.setIsDeleted(false);
        if (customerCompanyDTO.getGrade() == null) {
            customerCompanyEntity.setGrade(0);
        }
        return save(customerCompanyEntity);
    }


    @Override
    @Transactional
    public int list(MultipartFile file) {

        if (file.isEmpty()) {
            throw new BaseException(MessageConstant.FILE_IS_NULL);
        }
        List<CustomerCompanyEntity> dataList;

        try {
            CustomerCompanyListener listener = new CustomerCompanyListener(userMapper);
            EasyExcel.read(file.getInputStream(), CustomerCompanyExcel.class, listener).sheet().doRead();
            dataList = listener.getData();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        saveBatch(dataList);
        return dataList.size();
    }

    private void isValid(String phone) {
        if (!ValidationUtils.isValidMobile(phone)) {
            throw new BaseException(MessageConstant.IPHONE_IS_ERROR);
        }
    }

    @Override
    @Transactional
    public Integer updateList(List<CustomerCompanyDTO> customerCompanyDTOList) {

        List<CustomerCompanyEntity> customerCompanyEntityList = new ArrayList<>();

        for (CustomerCompanyDTO customerCompanyDTO : customerCompanyDTOList) {
            CustomerCompanyEntity customerCompanyEntity = new CustomerCompanyEntity();
            BeanUtils.copyProperties(customerCompanyDTO, customerCompanyEntity);
            customerCompanyEntity.setCreatorId(BaseUnit.getCurrentId());
            customerCompanyEntityList.add(customerCompanyEntity);
        }

        updateBatchById(customerCompanyEntityList);


        return customerCompanyEntityList.size();
    }

    @Override
    @Transactional
    public Integer deleteOrRecoverByIds(List<Long> idList, Boolean isRecover) {

        List<CustomerCompanyEntity> customerCompanyEntityList = new ArrayList<>();

        for (Long id : idList) {
            CustomerCompanyEntity customerCompanyEntity = new CustomerCompanyEntity();
            customerCompanyEntity.setId(id);
            customerCompanyEntity.setIsDeleted(isRecover);
            customerCompanyEntityList.add(customerCompanyEntity);
        }

        updateBatchById(customerCompanyEntityList);

        return idList.size();
    }

    /**
     * 物理删除多个客户公司数据
     *
     * @param idList 客户公司ID列表
     * @return 成功删除的公司数量
     * @throws BaseException 当ID列表为空时抛出异常
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Integer deleteByIds(List<Long> idList) {
        if (idList == null || idList.isEmpty()) {
            throw new BaseException(MessageConstant.ID_LIST_IS_NULL);
        }
        // 1. 删除公司关联的所有外键数据（使用配置的关联关系）
        // 资源类型：1-公司（对应DataShareEntity的resourceType）
        foreignKeyDeleteUtil.deleteCascade(CustomerCompanyEntity.class, idList, 1);

        // 2. 物理删除公司本身
        return customerCompanyMapper.deleteBatchIds(idList);
    }

    @Override
    public Boolean deleteById(Long id) {

        CustomerCompanyEntity customerCompanyEntity = new CustomerCompanyEntity();
        customerCompanyEntity.setId(id);
        customerCompanyEntity.setIsDeleted(true);

        this.updateById(customerCompanyEntity);

        // 级联删除联系人
        customerContactService.cascadeDeleteByCompanyId(id);

        // 级联删除销售机会
        salesOpportunityService.cascadeDeleteByCompanyId(id);


        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer logicalDeleteById(Long id) {
        return foreignKeyDeleteUtil.logicalDeleteByCascade(CustomerCompanyEntity.class, id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer batchLogicalDeleteByIds(List<Long> idList) {
        Integer totalDeleted = 0;
        for (Long id : idList) {
            totalDeleted += logicalDeleteById(id);
        }
        return totalDeleted;
    }

    /**
     * 根据联系人信息获取其所属公司信息
     *
     * @param id 联系人id
     * @return 公司信息VO对象
     * @throws BaseException 当联系人ID为空时抛出CONTACT_IS_NULL异常，当公司不存在时抛出COMPANY_IS_NULL异常
     */
    @Override
    @Privacy
    public CustomerCompanyVO getCompanyByCondition(Long id) {

        CustomerContactEntity customerContactEntity = customerContactMapper.selectById(id);
        Long companyId = customerContactEntity.getCompanyId();
        CustomerCompanyEntity customerCompanyEntity = baseMapper.selectById(companyId);
        String[] names = getCompanyNames(customerCompanyEntity);
        CustomerCompanyVO customerCompanyVO = CustomerCompanyVO.fromEntity(customerCompanyEntity, names[0], names[1]);

        return customerCompanyVO;
    }

    @Override
    public byte[] excel() {

        List<CustomerCompanyExcel> list = new ArrayList<>();

        List<CustomerCompanyEntity> entities = list(new LambdaQueryWrapper<CustomerCompanyEntity>()
                .eq(CustomerCompanyEntity::getIsDeleted, false));

        if (entities.isEmpty()) {
            throw new BaseException(MessageConstant.DATA_IS_NULL);
        }

        entities.forEach(entity -> {
            CustomerCompanyExcel excel = new CustomerCompanyExcel();
            BeanUtils.copyProperties(entity, excel);

            Long ownerId;
            //负责人名称、创建人名称
            if ((ownerId = entity.getOwnerId()) != null) {
                excel.setOwnerName(userMapper.selectById(ownerId).getRealName());
            }

            Long creatorId;
            if ((creatorId = entity.getCreatorId()) != null) {
                excel.setCreatorName(userMapper.selectById(creatorId).getRealName());
            }

            list.add(excel);
        });

        return aotoExcelUntil.AOTOExcelByStream(list, "客户公司");
    }

    @Override
    @Transactional
    public Boolean merge(CustomerMergeDTO customerMergeDTO) {

        CustomerMergeLogEntity entity = new CustomerMergeLogEntity();
        BeanUtils.copyProperties(customerMergeDTO, entity);
        entity.setOperatorId(BaseUnit.getCurrentId());

        //让被合并客户失效
        update(new LambdaUpdateWrapper<CustomerCompanyEntity>()
                .set(CustomerCompanyEntity::getIsDeleted, true)
                .eq(CustomerCompanyEntity::getId, customerMergeDTO.getMergedCompanyId()));

        //添加合并记录
        customerMergeLogMapper.insert(entity);

        return true;
    }

    @Override
    @Privacy
    public Page<CustomerCompanyVO> getAllCompany(Integer pageNum, Integer pageSize) {

        Page<CustomerCompanyVO> ans = new Page<>(pageNum, pageSize);

        Page<CustomerCompanyEntity> page = new Page<>(pageNum, pageSize);
        Page<CustomerCompanyEntity> pageResult = page(page, new LambdaQueryWrapper<CustomerCompanyEntity>()
                .eq(CustomerCompanyEntity::getIsDeleted, false));

        List<CustomerCompanyVO> customerCompanyVOList = pageResult.getRecords().stream()
                .map(entity -> {
                    String[] names = getCompanyNames(entity);
                    return CustomerCompanyVO.fromEntity(entity, names[0], names[1]);
                })
                .collect(Collectors.toList());

        BeanUtils.copyProperties(pageResult, ans);
        ans.setRecords(customerCompanyVOList);

        return ans;
    }

    @Override
    @Privacy
    public CustomerCompanyVO getCompanyDetail(Long id) {

        // 参数校验
        if (id == null) {
            throw new BaseException(MessageConstant.PARAM_ERROR);
        }

        CustomerCompanyEntity customerCompanyEntity = getById(id);
        if (customerCompanyEntity == null) {
            throw new BaseException(MessageConstant.COMPANY_IS_NOT_EXIST);
        }

        String[] names = getCompanyNames(customerCompanyEntity);
        CustomerCompanyVO customerCompanyVO = CustomerCompanyVO.fromEntity(customerCompanyEntity, names[0], names[1]);


        return customerCompanyVO;
    }

    @Override
    @Privacy
    public Page<CustomerCompanyVO> findCompany(String companyName, Integer pageNum, Integer pageSize) {
        LambdaQueryWrapper<CustomerCompanyEntity> wrapper = new LambdaQueryWrapper<>();
        wrapper.like(CustomerCompanyEntity::getCompanyName, companyName)
                .eq(CustomerCompanyEntity::getIsDeleted, false);

        Page<CustomerCompanyEntity> page = new Page<>(pageNum, pageSize);
        return getCustomerCompanyVOPage(wrapper, page);
    }

    /**
     * 分页获取客户公司VO列表
     *
     * @param wrapper  查询条件包装器
     * @param page     分页对象
     * @return 客户公司VO列表
     */
    private Page<CustomerCompanyVO> getCustomerCompanyVOPage(LambdaQueryWrapper<CustomerCompanyEntity> wrapper, Page<CustomerCompanyEntity> page) {
        Page<CustomerCompanyEntity> pageResult = page(page, wrapper);

        List<CustomerCompanyVO> list = pageResult.getRecords().stream()
                .map(entity -> {
                    String[] names = getCompanyNames(entity);
                    return CustomerCompanyVO.fromEntity(entity, names[0], names[1]);
                })
                .peek(this::setUserName)
                .collect(Collectors.toList());


        Page<CustomerCompanyVO> ans = new Page<>();
        BeanUtils.copyProperties(pageResult, ans);
        ans.setRecords(list);

        return ans;
    }

    @Override
    @Privacy
    public Page<CustomerCompanyVO> customQuery(CustomerCompanyDTO customerCompanyDTO, Integer pageNum, Integer pageSize) {
        if (pageNum == null || pageSize == null) {
            throw new BaseException(MessageConstant.DATA_IS_NULL);
        }

        Page<CustomerCompanyEntity> page = new Page<>(pageNum, pageSize);

        LambdaQueryWrapper<CustomerCompanyEntity> wrapper = new LambdaQueryWrapper<>();

        if (customerCompanyDTO.getCompanyName() != null) {
            wrapper.like(CustomerCompanyEntity::getCompanyName, customerCompanyDTO.getCompanyName());
        }
        if (customerCompanyDTO.getIndustry() != null) {
            wrapper.like(CustomerCompanyEntity::getIndustry, customerCompanyDTO.getIndustry());
        }
        if (customerCompanyDTO.getSource() != null) {
            wrapper.like(CustomerCompanyEntity::getSource, customerCompanyDTO.getSource());
        }
        if (customerCompanyDTO.getAddress() != null) {
            wrapper.like(CustomerCompanyEntity::getAddress, customerCompanyDTO.getAddress());
        }
        if (customerCompanyDTO.getPhone() != null) {
            wrapper.like(CustomerCompanyEntity::getPhone, customerCompanyDTO.getPhone());
        }
        if (customerCompanyDTO.getWebsite() != null) {
            wrapper.like(CustomerCompanyEntity::getWebsite, customerCompanyDTO.getWebsite());
        }
        if (customerCompanyDTO.getDescription() != null) {
            wrapper.like(CustomerCompanyEntity::getDescription, customerCompanyDTO.getDescription());
        }
        if (customerCompanyDTO.getIsDeleted() != null) {
            wrapper.eq(CustomerCompanyEntity::getIsDeleted, customerCompanyDTO.getIsDeleted());
        }
        return getCustomerCompanyVOPage( wrapper, page);
    }

    /**
     * 根据wrapper查询名称
     *
     * @param wrapper 查询条件包装器
     * @return 客户公司VO列表
     */
    private List<CustomerCompanyVO> getCustomerCompanyVOS(LambdaQueryWrapper<CustomerCompanyEntity> wrapper) {
        return list(wrapper).stream()
                .map(entity -> {
                    String[] names = getCompanyNames(entity);
                    return CustomerCompanyVO.fromEntity(entity, names[0], names[1]);
                })
                .peek(this::setUserName)
                .collect(Collectors.toList());
    }

    /**
     * 设置客户公司VO的负责人名称、创建人名称
     *
     * @param customerCompanyVO 客户公司VO对象
     */
    private void setUserName(CustomerCompanyVO customerCompanyVO) {
        Long ownerId;
        if ((ownerId = customerCompanyVO.getOwnerId()) != null) {
            customerCompanyVO.setOwnerName(userMapper.selectById(ownerId).getRealName());
        }
        Long creatorId;
        if ((creatorId = customerCompanyVO.getCreatorId()) != null) {
            customerCompanyVO.setCreatorName(userMapper.selectById(creatorId).getRealName());
        }
    }

    /**
     * 获取客户公司的创建人名称和负责人名称
     *
     * @param entity 客户公司实体
     * @return 包含创建人名称和负责人名称的数组
     */
    private String[] getCompanyNames(CustomerCompanyEntity entity) {
        String creatorName = null;
        String ownerName = null;

        if (entity.getCreatorId() != null) {
            UserEntity creator = userMapper.selectById(entity.getCreatorId());
            if (creator != null) {
                creatorName = creator.getRealName();
            }
        }

        if (entity.getOwnerId() != null) {
            UserEntity owner = userMapper.selectById(entity.getOwnerId());
            if (owner != null) {
                ownerName = owner.getRealName();
            }
        }

        return new String[]{creatorName, ownerName};
    }

    @Override
    public GroupResultVO groupByCustomerCompany(String field) {

        // 检查字段是否有效
        if (!Arrays.asList("industry", "source", "ownerId").contains(field)) {
            throw new BaseException(MessageConstant.GROUP_FIELD_IS_ERROR);
        }

        LambdaQueryWrapper<CustomerCompanyEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(CustomerCompanyEntity::getIsDeleted, false);

        List<CustomerCompanyEntity> entities = customerCompanyMapper.selectList(queryWrapper);
        Map<Object, List<CustomerCompanyVO>> groupMap = new HashMap<>();

        // 按不同字段分组
        for (CustomerCompanyEntity entity : entities) {
            String[] names = getCompanyNames(entity);
            CustomerCompanyVO vo = CustomerCompanyVO.fromEntity(entity, names[0], names[1]);

            Object groupKey = getGroupKey(entity, field);
            if (groupKey == null) {
                continue;
            }

            groupMap.computeIfAbsent(groupKey, k -> new ArrayList<>()).add(vo);
        }

        GroupResultVO resultVO = new GroupResultVO();
        resultVO.setGroupField(field);
        resultVO.setGroupData(groupMap);
        return resultVO;
    }

    private Object getGroupKey(CustomerCompanyEntity entity, String field) {
        return switch (field) {
            case "industry" -> entity.getIndustry();
            case "source" -> entity.getSource();
            case "ownerId" -> entity.getOwnerId();
            default -> null;
        };
    }

    @Override
    public byte[] template() {
        List<GetCustomerCompanyExcel> customerCompanyExcels = new ArrayList<>();
        customerCompanyExcels.add(new GetCustomerCompanyExcel());
        return aotoExcelUntil.AOTOExcelByStream(customerCompanyExcels, "customer_company_template.xlsx");
    }
}
